package com.pmmaster.common.utils;

import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.UUID;
import java.util.regex.Pattern;

public class StringUtil {
    public final static String dateFormat = "yyyyMMdd";

    public static String[] chars = new String[]{"a", "b", "c", "d", "e", "f",
        "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
        "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5",
        "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I",
        "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
        "W", "X", "Y", "Z"};
    /**
     * 常用正则表达式：匹配非负整数（正整数 + 0）
     */
    public final static String regExp_integer_1 = "^\\d+$";

    /**
     * 常用正则表达式：匹配正整数
     */
    public final static String regExp_integer_2 = "^[0-9]*[1-9][0-9]*$";

    /**
     * 常用正则表达式：匹配非正整数（负整数 + 0）
     */
    public final static String regExp_integer_3 = "^((-\\d+) ?(0+))$";

    /**
     * 常用正则表达式：匹配负整数
     */
    public final static String regExp_integer_4 = "^-[0-9]*[1-9][0-9]*$";

    /**
     * 常用正则表达式：匹配整数
     */
    public final static String regExp_integer_5 = "^-?\\d+$";

    /**
     * 常用正则表达式：匹配非负浮点数（正浮点数 + 0）
     */
    public final static String regExp_float_1 = "^\\d+(\\.\\d+)?$";

    /**
     * 常用正则表达式：匹配正浮点数
     */
    public final static String regExp_float_2 = "^(([0-9]+\\.[0-9]*[1-9][0-9]*) ?([0-9]*[1-9][0-9]*\\.[0-9]+) ?([0-9]*[1-9][0-9]*))$";

    /**
     * 常用正则表达式：匹配非正浮点数（负浮点数 + 0）
     */
    public final static String regExp_float_3 = "^((-\\d+(\\.\\d+)?) ?(0+(\\.0+)?))$";

    /**
     * 常用正则表达式：匹配负浮点数
     */
    public final static String regExp_float_4 = "^(-(([0-9]+\\.[0-9]*[1-9][0-9]*) ?([0-9]*[1-9][0-9]*\\.[0-9]+) ?([0-9]*[1-9][0-9]*)))$";

    /**
     * 常用正则表达式：匹配浮点数
     */
    public final static String regExp_float_5 = "^(-?\\d+)(\\.\\d+)?$";

    /**
     * 常用正则表达式：匹配由26个英文字母组成的字符串
     */
    public final static String regExp_letter_1 = "^[A-Za-z]+$";

    /**
     * 常用正则表达式：匹配由26个英文字母的大写组成的字符串
     */
    public final static String regExp_letter_2 = "^[A-Z]+$";

    /**
     * 常用正则表达式：匹配由26个英文字母的小写组成的字符串
     */
    public final static String regExp_letter_3 = "^[a-z]+$";

    /**
     * 常用正则表达式：匹配由数字和26个英文字母组成的字符串
     */
    public final static String regExp_letter_4 = "^[A-Za-z0-9]+$";

    /**
     * 常用正则表达式：匹配由数字、26个英文字母或者下划线组成的字符串
     */
    public final static String regExp_letter_5 = "^\\w+$";

    /**
     * 常用正则表达式：匹配email地址
     */
    public final static String regExp_email = "^[\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$";

    /**
     * 常用正则表达式：匹配url
     */
    public final static String regExp_url_1 = "^[a-zA-z]+://(\\w+(-\\w+)*)(\\.(\\w+(-\\w+)*))*(\\?\\S*)?$";

    /**
     * 常用正则表达式：匹配url
     */
    public final static String regExp_url_2 = "[a-zA-z]+://[^\\s]*";

    /**
     * 常用正则表达式：匹配中文字符
     */
    public final static String regExp_chinese_1 = "[\\u4e00-\\u9fa5]";

    /**
     * 常用正则表达式：匹配双字节字符(包括汉字在内)
     */
    public final static String regExp_chinese_2 = "[^\\x00-\\xff]";

    /**
     * 常用正则表达式：匹配空行
     */
    public final static String regExp_line = "\\n[\\s ? ]*\\r";

    /**
     * 常用正则表达式：匹配HTML标记
     */
    public final static String regExp_html_1 = "/ <(.*)>.* <\\/\\1> ? <(.*) \\/>/";

    /**
     * 常用正则表达式：匹配首尾空格
     */
    public final static String regExp_startEndEmpty = "(^\\s*) ?(\\s*$)";

    /**
     * 常用正则表达式：匹配帐号是否合法(字母开头，允许5-16字节，允许字母数字下划线)
     */
    public final static String regExp_accountNumber = "^[a-zA-Z][a-zA-Z0-9_]{4,15}$";

    /**
     * 常用正则表达式：匹配国内电话号码，匹配形式如 0511-4405222 或 021-87888822
     */
    public final static String regExp_telephone = "\\d{3}-\\d{8} ?\\d{4}-\\d{7}";

    /**
     * 常用正则表达式：腾讯QQ号, 腾讯QQ号从10000开始
     */
    public final static String regExp_qq = "[1-9][0-9]{4,}";

    /**
     * 常用正则表达式：匹配中国邮政编码
     */
    public final static String regExp_postbody = "[1-9]\\d{5}(?!\\d)";

    /**
     * 常用正则表达式：匹配身份证, 中国的身份证为15位或18位
     */
    public final static String regExp_idCard = "^(\\d{6})(\\d{4})(\\d{2})(\\d{2})(\\d{3})([0-9]|X)$";

    /**
     * 常用正则表达式：IP
     */
    public final static String regExp_ip = "\\d+\\.\\d+\\.\\d+\\.\\d+";

    /**
     * 常用正则表达式：手机号码
     */
    public final static String regExp_phone = "^1[34578]{1}[0-9]{9}$";

    /**
     * 字符编码
     */
    public final static String encoding = "UTF-8";

    /**
     * 常用正则表达式：密码包含字母和数字，长度为6-20位
     */
    public final static String passwordMatch = "^(?![^0-9]+$)(?![^a-zA-Z]+$).+$";

    public static final String allChar = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

    /**
     * 首字母转大写
     *
     * @param s 参数
     * @return String 首字母转大写
     */
    public static String toUpperCaseFirstOne(String s) {
        if (Character.isUpperCase(s.charAt(0))) {
            return s;
        } else {
            return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
        }
    }

    /**
     * 格式化钱，保留小数点后两位
     *
     * @param money 金额
     * @return 处理结果，保留小数后两位
     */
    public static String formatMoney(Object money) {
        DecimalFormat df = new DecimalFormat("0.00");
        return df.format(null2Double(money));
    }

    /**
     * 将null对象转换为空字符串""
     *
     * @param s 待判断的对象
     * @return 转换后的字符串
     */
    public static String null2String(Object s) {
        return s == null ? "" : s.toString().trim();
    }

    /**
     * 将字符串数字转换为double数字
     *
     * @param s 字符串数字
     * @return double数字，如果是null，返回0.0
     */
    public static double null2Double(Object s) {
        double v = 0.0;
        if (s != null) {
            try {
                v = Double.parseDouble(null2String(s));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return v;
    }

    /**
     * 格式化钱，保留小数点后两位
     *
     * @param money                         金额
     * @param mode（RoundingMode.FLOOR非四舍五入）
     * @return 处理结果，保留小数后两位
     */
    public static String formatMoney(Object money, RoundingMode mode) {
        DecimalFormat df = new DecimalFormat("0.00");
        df.setRoundingMode(mode);
        return df.format(money);
    }

    /**
     * 首字母转小写
     *
     * @param s 参数
     * @return String 首字母转小写
     */
    public static String toLowerCaseFirstOne(String s) {
        if (Character.isLowerCase(s.charAt(0))) {
            return s;
        } else {
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
        }
    }

    /**
     * 字符串是否为空白 空白的定义如下： <br>
     * 1、为null <br>
     * 2、为不可见字符（如空格）<br>
     * 3、""<br>
     *
     * @param str 被检测的字符串
     * @return 是否为空
     */
    public static boolean isBlank(String str) {
        int length;

        if ((str == null) || ((length = str.length()) == 0)) {
            return true;
        }

        for (int i = 0; i < length; i++) {
            // 只要有一个非空字符即为非空字符串
            if (!Character.isWhitespace(str.charAt(i))) {
                return false;
            }
        }

        return true;
    }

    /**
     * 判断是否为非法的请求：
     * 1、SQL注入
     * 2、跨站脚本
     *
     * @param str 参数
     * @return boolean 是否为非法的请求
     */
    public static boolean isValid(String str) {
        return isValidSqlInput(str) && isValidScriptInput(str);
    }

    /**
     * 判断是否为合法的SQL输入，使用正则表达式防止SQL注入
     *
     * @param str 参数
     * @return boolean 是否为合法的SQL输入
     */
    public static boolean isValidSqlInput(String str) {
        String reg = "(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|"
            + "(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)";
        Pattern sqlPattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE);
        if (sqlPattern.matcher(str).find()) {
            return false;
        }
        return true;
    }

    /**
     * 判断是否为合法的脚本输入，使用正则表达式防止跨站脚本
     *
     * @param str 参数
     * @return boolean 合法的脚本输入
     */
    public static boolean isValidScriptInput(String str) {
        String regEx_xml = "<xml[^>]*?>[\\s\\S]*?<\\/xml>"; //定义xml的正则表达式
        String regEx_script = "<script[^>]*?>[\\s\\S]*?<\\/script>"; //定义script的正则表达式
        String regEx_style = "<style[^>]*?>[\\s\\S]*?<\\/style>"; //定义style的正则表达式
        String regEx_html = "<[^>]+>"; //定义HTML标签的正则表达式
        String reg = regEx_xml + regEx_script + regEx_style + regEx_html;
        Pattern sqlPattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE);
        if (sqlPattern.matcher(str).find()) {
            return false;
        }
        return true;
    }

    /**
     * 生成指定长度的随机字符串
     *
     * @param length
     * @return
     */
    public static String randomStr(int length) {
        StringBuffer sb = new StringBuffer();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            sb.append(allChar.charAt(random.nextInt(allChar.length())));
        }
        return sb.toString();
    }

    /**
     * 数组转字符串
     *
     * @param string
     * @param delimiter
     * @return
     */
    public static String implode(String[] string, String delimiter) {
        StringBuffer str = new StringBuffer();
        for (String s : string) {
            str.append(s + delimiter);
        }
        return str.toString();
    }

    /**
     * 字符串转数组
     *
     * @param string
     * @param delimiter
     * @return
     */
    public static String[] explode(String string, String delimiter) {
        return string.split(delimiter);
    }

    /**
     * 字符串转数组
     *
     * @param string
     * @param delimiter
     * @return
     */
    public static String[] split(String string, String delimiter) {
        return string.split(delimiter);
    }

    /**
     * 生成一个11位的短UUID
     *
     * @return String 11位的短UUID
     */
    public static String generateShortUuid() {
        StringBuffer shortBuffer = new StringBuffer();
        String uuid = UUID.randomUUID().toString().replace("-", "");
        for (int i = 0; i < 11; i++) {
            String str = uuid.substring(i * 2, i * 2 + 2);
            int x = Integer.parseInt(str, 16);
            shortBuffer.append(chars[x % 0x3E]);
        }
        return shortBuffer.toString();
    }

    /**
     * 获取流水号 28位渠道流水号
     *
     * @param transcode 交易码
     * @return 整数的字符串
     */
    public static final String getFlow(String transcode) {
        int start = transcode.length() - 3;
        String code = transcode.substring(start);
        StringBuffer bf = new StringBuffer();
        bf.append("").append(formatDateStr(new Date())).append(code).append(generateShortUuid());
        return bf.toString();
    }

    /**
     * 获取流水号 20位
     *
     * @return String 整数的字符串
     */
    public static final String getFlow() {
        return formatLongDateStr(new Date()) + randomInt(4);
    }

    /**
     * 获取随机的一个整数字符串
     *
     * @param length 整数字符串的长度
     * @return 整数的字符串
     */
    public static final String randomInt(int length) {
        if (length < 1) {
            return null;
        }
        Random randGen = new Random();
        char[] numbersAndLetters = "0123456789".toCharArray();

        char[] randBuffer = new char[length];
        for (int i = 0; i < randBuffer.length; i++) {
            randBuffer[i] = numbersAndLetters[randGen.nextInt(10)];
        }
        return new String(randBuffer);
    }

    /**
     * 转换为长格式字符串 yyyyMMdd
     *
     * @param v 时间对象
     * @return 时间字符串
     */
    public static String formatDateStr(Object v) {
        if (v == null || "".equals(v)) {
            return "";
        }
        SimpleDateFormat df = new SimpleDateFormat(StringUtil.dateFormat);
        return df.format(v);
    }

    /**
     * 转换为长格式字符串 yyyyMMddHHmmss
     *
     * @param v 时间对象
     * @return 时间字符串
     */
    public static String formatLongDateStr(Object v) {
        if (v == null || "".equals(v)) {
            return "";
        }
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
        return df.format(v);
    }

    /**
     * 获取随机字符串
     *
     * @param length 字符串的长度
     * @return 返回的随机字符串
     */
    public static final String randomString(int length) {
        char[] numbersAndLetters = ("0123456789abcdefghijklmnopqrstuvwxyz" + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")
            .toCharArray();
        if (length < 1) {
            return "";
        }
        Random randGen = new Random();
        char[] randBuffer = new char[length];
        for (int i = 0; i < randBuffer.length; i++) {
            randBuffer[i] = numbersAndLetters[randGen.nextInt(71)];
        }
        return new String(randBuffer);
    }

    /**
     * 在字符串中隐藏重要的信息，以*号替换
     *
     * @param str   待隐藏字符串
     * @param begin 开始位置
     * @param end   结束位置
     * @return genericStar 隐藏后的字符串
     */
    public static String genericStar(String str, int begin, int end) {
        if (str.length() > begin && str.length() >= end) {
            return str.replaceAll(str.substring(begin, end), "****");
        } else {
            return str;
        }
    }

    /**
     * 随机生成UUID 32位字符串
     *
     * @return String uuid
     */
    public static String getUUID() {
        return UUID.randomUUID().toString().replace("-", "");
    }
}

